import math
from pyproj import Transformer
from urllib.request import urlretrieve
from urllib.error import HTTPError
import os
import cv2
import numpy as np

EXTENDS_3857 = 20037508.342789244


def get_tile_index(level, tms_type, x_min, x_max, y_min, y_max):
    """
    获取矩形范围内指定的等级的瓦片索引
    :param level:  等级
    :param tms_type: TMS规则类型，0谷歌，1标准TMS
    :param x_min: x最小值
    :param x_max: x最大值
    :param y_min: y最小值
    :param y_max: y最大值
    :return:
    """
    tile_list = []
    tile_size = EXTENDS_3857 / math.pow(2, level - 1)
    x1 = math.ceil((x_min + EXTENDS_3857) / tile_size) - 1  # 起始X,减1是因为从0开始

    x2 = math.ceil((x_max + EXTENDS_3857) / tile_size) - 1  # 终止X

    if tms_type == 0:
        # 谷歌地图TMSy值计算
        y1 = math.ceil((EXTENDS_3857 - y_max) / tile_size) - 1  # 起始y
        y2 = math.ceil((EXTENDS_3857 - y_min) / tile_size) - 1  # 终止y
    else:
        # 标准TMSy值计算
        y1 = math.ceil((y_min + EXTENDS_3857) / tile_size) - 1  # 起始y
        y2 = math.ceil((y_max + EXTENDS_3857) / tile_size) - 1  # 终止y

    # 防止计算产生负值
    if x1 < 0:
        x1 = 0
    if x2 < 0:
        x2 = 0
    if y1 < 0:
        y1 = 0
    if y2 < 0:
        y2 = 0
    for j in range(x1, x2 + 1):
        for k in range(y1, y2 + 1):
            tile_list.append([j, k, level])
    return tile_list


def get_coord_by_index(x, y, level, tms_type=0):
    """
    通过瓦片索引，计算左上角坐标
    :param x:
    :param y:
    :param level:
    :param tms_type:
    :return:
    """
    tile_size = get_tile_size(level)
    x_coord = x * tile_size - EXTENDS_3857
    if tms_type == 0:
        # 谷歌地图TMSy值计算
        y_coord = EXTENDS_3857 - y * tile_size

    else:
        # 标准TMSy值计算
        y_coord = (y + 1) * tile_size

    return [x_coord, y_coord]


def get_coord_by_index_w_s(x, y, level, tms_type=0):
    """
    通过瓦片索引，计算左下角坐标
    :param x:
    :param y:
    :param level:
    :param tms_type:
    :return:
    """
    tile_size = get_tile_size(level)
    x_coord = x * tile_size - EXTENDS_3857
    if tms_type == 0:
        # 谷歌地图TMSy值计算
        y_coord = EXTENDS_3857 - (y + 1) * tile_size

    else:
        # 标准TMSy值计算
        y_coord = y * tile_size

    return [x_coord, y_coord]


def get_tile_size(level):
    """
    获取指定等级下一个瓦片的大小
    :param level: 地图等级
    :return: 瓦片实际大小
    """
    return EXTENDS_3857 / math.pow(2, level - 1)


def wgs_84_to_mector(lat, lng):
    """
    经纬度坐标转墨卡托坐标
    :param lat: 纬度
    :param lng: 经度
    :return:
    """
    if lat > 85:
        lat = 85
    elif lat < -85:
        lat = -85

    transformer = Transformer.from_crs("epsg:4326", "epsg:3857")
    x2, y2 = transformer.transform(lat, lng)

    return [x2, y2]


def replace_url(url, x, y, z):
    """
    将url中的xyz替换
    :param url: url
    :param x: x
    :param y: y
    :param z: z
    :return: 替换后的url
    """
    return url.format(x=x, y=y, z=z)


def down_img(url, position, x, y, z):
    print("下载", z, x, y)
    url = replace_url(url, x, y, z)
    if url.find(".jpg") > -1:
        file_type = ".jpg"
    else:
        file_type = ".png"
    folder = r'{position}\{z}\{x}'.format(position=position, z=z, x=x)

    if not os.path.exists(folder):
        os.makedirs(folder)

    target = r'\{y}{file_type}'.format(y=y, file_type=file_type)
    try:
        urlretrieve(url, folder + target)
    except HTTPError:
        create_empty(folder + target)
        print("下载失败", z, x, y)


def create_empty(path):
    """
    生成一张256*256的图片
    :param path:
    :return:
    """
    x = np.zeros([256, 256, 3], dtype=np.uint8)
    cv2.imwrite(path, x)


if __name__ == '__main__':
    down_img(
        "http://tiebapic.baidu.com/forum/w/sign=ccf1647252b30f24359aec0bf8aed043/f9198618367adab4fd95d450d4b31c8701e459.jpg",
        "", 1, 1, 1)
